// 导入 axios
import axios from 'axios'

// 6月26号-----------------6月26号---------------------------
// api/my.js里面的 token 工具函数删除了,  headers 携带的token也删除了
// 导入utils/token,js工具函数
/* eslint-disable */
import { getToken, removeToken, saveToken } from '../utils/token.js'
// 6月30号----------修改,在上面添加了removeToken----------6月30号-------------
// 6月30号---------------------6月30号------------------
import { Toast } from 'vant'
// 导入router(跳转到login页面是需要用)
import router from '../router/index.js'

// create一个副本
const instance = axios.create({
  // 基地址
  baseURL: 'http://toutiao-app.itheima.net'
})

// 6月26号-----------------6月26号--------------------------
// 注册axios拦截器 (就是一个回调函数 钩子函数一样)
// 作用就是为当前的请求对象instance注册了两个回调函数(一个是发送请求之前的回调函数)(另外一个是数据回来以后的回调函数)
// 目前是没有在下面的响应拦截器里面做事情，目前只在请求拦截器里面做了事情
// api/my.js里面的 token 工具函数删除了,  headers 携带的token也删除了

// 添加 请求拦截器
instance.interceptors.request.use(
  // config 配置的意思  这次请求的选项, 是一个请求头
  function (config) {
    // 在发送请求之前做些什么------------------
    // 可以拿到请求头 和设置请求头
    // console.log('request拦截器')
    // 打印出来是config的一个对象,里面的值就是当前这一次请求的所有的设置,然后因为他是一个对象,所以就动态为他设置任何你想设置的东西
    // 比如说 headers(请求头的意思), 请求拦截器是可以去拿到请求头并且设置请求头的(这就是请求拦截器的作用)
    // console.log('config', config)
    const tokenObj = getToken()
    // console.log('tokenObj:', tokenObj)
    if (tokenObj !== null) {
      // 有token就设置token (因为我们后期调用的很多接口都需要携带token,尤其是设计到用户信息的)  (这里是需要请求参数的 Authorization)
      // 最开始是在my.js这个文件里面直接在发送请求的时候把token带过去(这么做是没有问题的)
      // 但是如果你有多个接口都需要带token,那么my.js里面的 getUserInfo 方法里面的代码就需要写很多次
      // 所以axios拦截器的作用不需要写很多次,直接把my.js里面的 getUserInfo方法里面的代码抽取一下,抽到 request.js这个页面
      // 这里的作用是,每次发送请求的时候,它都会先执行一下拦截器里面的代码(就是一个回调函数),所以在回调函数里面做判断
      // 如果 tokenObj !== null 就是本地有token 那就把token带到这个接口里面需要的这个字段里面 Authorization里面
      // 这样的话,不管在这个项目的哪一个地方发请求,只要本地有token就一定会把这个token带到服务器里面去
      // 这样在my.js的页面就不需要去设置token了,就可以删除那边的了, 后续如果有多个接口,只要涉及到token的携带,都不需要写headers了
      // 因为都已经在拦截器里面把他设置上去了
      config.headers.Authorization = `Bearer ${getToken().token}`
    }
    return config
  },
  function (error) {
    // 对请求错误做些什么---------------
    return Promise.reject(error)
  }
)
// 6月30号----------修改----------6月30号-----------------月30号-------
// 添加 响应拦截器
// token异常判断是写在response里面的,响应回来就会进到response截器中
// 需求分析:如果请求出现了异常,就需要删除token,返回登陆页面,然后登陆成功后,返回原始页面
instance.interceptors.response.use(
  // response 响应内容  success成功的意思
  function (response) {
    // 注意注意 token正常的的时候 会执行这里的代码(通过下面的打印即可知晓)
    console.log('response拦截器-success成功的意思')
    // 对响应数据做点什么-----------------
    return response
  },
  async function (error) {
    // token就是登陆的凭证,需要登录的接口携带`token`就知道你是谁
    // refresh_token就是刷新token,为什么要有刷新token,`token`过期时间一般不会太久,项目中`2`小时
    // 为了让`token`过期,用户可以平滑的获取新`token`,refresh_token的作用就是:结合接口获取新的`token`
    // refresh_token的过期时间是14天,作用解决的问题就是:偷偷利用refresh_token去更新本地的token
    // 用户就不会没有了token,这就是refresh_token的作用
    // 注意这里的代码需要 token 和refresh_token两个都改错的情况下才能生效,(refresh_token是在token数据的最后面去随机修改一个值即可)
    if (error.response.status === 401 && getToken() !== null) {
      try {
        // 这里不抽取api 直接用 axios 来发请求 默认的instance已经设置携带token啦
        // 因为默认的请求对象 instance 它已经设置了基地址,并且还设置了一个请求拦截器
        // 所以他会自动的从缓存里面读取token,但是这个token都过期了(而这里面要的是refresh_token)
        // 所以自己来带refresh_token,因为默认的用不了
        // (刷新用户token的接口地址 /v1_0/authorizations) method: 'put',
        // 注意这个接口是需要带参数 Authorization 的,值是refresh_token,(需要从getToken()里面才能拿到)
        const getTokenRes = await axios({
          url: 'http://toutiao-app.itheima.net/v1_0/authorizations',
          method: 'put',
          headers: {
            Authorization: `Bearer ${getToken().refresh_token}`
          }
        })
        // 打印出来的data.data.token是有token数据的(说明拿到了刷新的token)
        // console.log('getTokenRes:', getTokenRes)
        // 拿到刷新的token后,更新本地的token
        const tokenObj = getToken()
        // 这样的效果是本地的token也更新完了,但是缓存里面的还没有更新,所以写入缓存中
        tokenObj.token = getTokenRes.data.data.token
        // 写入缓存(把原本保存token的对象tokenObj{在utils/token.js里面})取出来改动一下,然后又把他重新写入回去
        // 作用是,当本地的token是错误的时候,就会重新去获取一次token,并且获取到后会重新更新
        saveToken(tokenObj)
        // 这里打印出来error里面有config,有基地址baseURL: "http://toutiao-app.itheima.net"
        // 还有url地址url: "/v1_0/user/profile" 还有token Authorization:""
        // 这个 config 就是当前发送的,这一次请求,原本请求的那些设置就在这个config里面
        // 所以 error中的config就是这次的请求配置(那么取出来重新发送请求就行return instance(error.config))
        // console.dir(error)
        // 重新获取到token后,需要重新发送一下请求, (instance是响应拦截器创建的对象)
        return instance(error.config)
        // 上面这些代码的作用:就是用户在长时间没有操作页面,在此调请求,依旧可以包装token是拿到最新的
        // 不会直接崩溃让用户直接去登陆
      } catch (error) {
        // 捕获异常用  try catch
        // 错误会进来 请求失败
        // refresh_token有问题才会执行这里的代码
        // console.dir(error)
        Toast.fail('请重新登录')
        removeToken()
        // 去登陆
        router.push({
          path: '/login',
          query: { back: router.history.current.fullPath }
        })
        // 如果觉得控制台异常报错不好看, 可以清除(小白不建议清除)
        // setTimeout(() => {
        //   console.clear()
        // }, 0)
        // 抛出异常
        return Promise.reject(error)
      }
    }
  }
  // 6月30号----------修改----------6月30号-----------------
  // token异常判断
  // error失败的意思
  // function (error) {
  //   // 注意注意 只要token错误的时候(比如401 400 405) 都会执行这里的代码(通过下面的打印即可知晓)
  //   console.log('response拦截器-error失败的意思')
  //   // 打印出来的error数据里面有response里面有status状态401
  //   // 所以就会认为token是有错的 (为什么有错?暂时先不管)
  //   // console.dir(error)
  //   // 对响应错误做点什么---------------
  //   // 这里只是基础判断
  //   if (error.response.status === 401) {
  //     // 说明token有问题,提示去登陆,然后删除token
  //     Toast.fail('请重新登陆')
  //     removeToken()
  //     // 输入的是一个对象,打印的是内存地址(token改错后,刷新后跳转的页面后,得到的结果是登陆页面的)
  //     // 而在这个对象里面是有router.history.current.path和router.history.current.fullPath
  //     console.log('router', router)
  //     console.log(router.history.current.path) // 这种拿不到完整地址(通过 ?号键值对带的页面 得这个/result)
  //     // 上面得path只能获取普通地址,(就是params携带数据的地址)
  //     // 这个可以拿到所有的地址(直接获取完整的地址包括?key=value)
  //     // 所以如果需要登陆成功可以正常返回原始页面,就需要用fullPath
  //     console.log(router.history.current.fullPath) // 这个可以拿到完整地址,通过 ?号键值对带的页面 得/result?q=%E4%BD%A0%E5%A5%BD
  //     return router.push({
  //       path: '/login',
  //       query: { back: router.history.current.fullPath }
  //     })
  //   }
  //   // 对响应错误做点什么
  //   return Promise.reject(error)
  // }
)
// 暴露 instance
export default instance
